package xmlTest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.dom4j.*;
import org.dom4j.xpath.DefaultXPath;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

/**
 * @desc
 * @author xukai
 * @date
 */
public class XmlParserUtil {

    private static String modelXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<wsdl:definitions xmlns:tns=\"www.ns2.com\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " +
            "xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" " +
            "name=\"himapEntryService\" targetNamespace=\"www.ns2.com\"><wsdl:types><xs:schema xmlns:xs=\"http://www" +
            ".w3.org/2001/XMLSchema\" targetNamespace=\"www.ns2.com\" elementFormDefault=\"unqualified\" version=\"1" +
            ".0\"><xs:element name=\"licenseInfo\" type=\"tns:licenseInfo\"/><xs:complexType name=\"licenseInfo\"><xs:sequence><xs:element name=\"username\" type=\"xs:string\"/><xs:element name=\"password\" type=\"xs:string\"/></xs:sequence></xs:complexType></xs:schema></wsdl:types><wsdl:message name=\"licenseInfo\"><wsdl:part name=\"licenseInfo\" element=\"tns:licenseInfo\"/></wsdl:message><wsdl:portType name=\"service\"></wsdl:portType><wsdl:binding name=\"himapEntryServiceSoapBinding\" type=\"tns:service\"><soap:binding style=\"document\" transport=\"http://schemas.xmlsoap.org/soap/http\"/></wsdl:binding><wsdl:service name=\"himapEntryService\"><wsdl:port name=\"himapEntryPort\" binding=\"tns:himapEntryServiceSoapBinding\"><soap:address location=\"http://127.0.0.1:8076/webServices2?groupName=\"/></wsdl:port></wsdl:service></wsdl:definitions>";

    private static String xml1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<wsdl:definitions xmlns:tns=\"http://ws.server.himap.com/demo\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" name=\"himapEntryService\" targetNamespace=\"http://ws.server.himap.com/demo\"><wsdl:types><xs:schema xmlns:tns=\"http://ws.server.himap.com/demo\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://ws.server.himap.com/demo\" elementFormDefault=\"unqualified\" version=\"1.0\"><xs:element name=\"demo_Request\" type=\"tns:demo_Request\"/><xs:element name=\"demo_Response\" type=\"tns:demo_Response\"/><xs:complexType name=\"demo_Request\"><xs:sequence><xs:element maxOccurs=\"unbounded\" minOccurs=\"0\" name=\"request\" type=\"tns:demo_RequestRecord\"/></xs:sequence></xs:complexType><xs:complexType name=\"demo_Response\"><xs:sequence><xs:element maxOccurs=\"unbounded\" minOccurs=\"0\" name=\"response\" type=\"tns:demo_ResponseRecord\"/></xs:sequence></xs:complexType><xs:complexType name=\"demo_RequestRecord\"><xs:sequence><xs:element minOccurs=\"0\" name=\"startDate\" type=\"xs:int\"/></xs:sequence></xs:complexType><xs:complexType name=\"demo_ResponseRecord\"><xs:sequence><xs:element minOccurs=\"0\" name=\"fdate\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"numbers\" type=\"xs:string\"/></xs:sequence></xs:complexType></xs:schema></wsdl:types><wsdl:message name=\"demo_Request\"><wsdl:part name=\"parameters\" element=\"tns:demo_Request\"/></wsdl:message><wsdl:message name=\"demo_Response\"><wsdl:part name=\"parameters\" element=\"tns:demo_Response\"/></wsdl:message><wsdl:portType name=\"demo\"><wsdl:operation name=\"demo\"><wsdl:input name=\"demo_Request\" message=\"tns:demo_Request\"/><wsdl:output name=\"demo_Response\" message=\"tns:demo_Response\"/></wsdl:operation></wsdl:portType><wsdl:binding name=\"himapEntryServiceSoapBinding\" type=\"tns:demo\"><soap:binding style=\"document\" transport=\"http://schemas.xmlsoap.org/soap/http\"/><wsdl:operation name=\"demo\"><soap:operation soapAction=\"urn:demo\" style=\"document\"/><wsdl:input name=\"demo_Request\"><soap:body use=\"literal\"/></wsdl:input><wsdl:output name=\"demo_Response\"><soap:body use=\"literal\"/></wsdl:output></wsdl:operation></wsdl:binding><wsdl:service name=\"himapEntryService\"><wsdl:port name=\"himapEntryPort\" binding=\"tns:himapEntryServiceSoapBinding\"><soap:address location=\"http://192.168.0.222:9222/himapws/webServices/himapEntryPort\"/></wsdl:port></wsdl:service></wsdl:definitions>";

    private static String xml2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<wsdl:definitions xmlns:tns=\"http://ws.server.himap.com/GetStopInfo\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" name=\"himapEntryService\" targetNamespace=\"http://ws.server.himap.com/GetStopInfo\"><wsdl:types><xs:schema xmlns:tns=\"http://ws.server.himap.com/GetStopInfo\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://ws.server.himap.com/GetStopInfo\" elementFormDefault=\"unqualified\" version=\"1.0\"><xs:element name=\"GetStopInfo_Request\" type=\"tns:GetStopInfo_Request\"/><xs:element name=\"GetStopInfo_Response\" type=\"tns:GetStopInfo_Response\"/><xs:complexType name=\"GetStopInfo_Request\"><xs:sequence><xs:element maxOccurs=\"unbounded\" minOccurs=\"0\" name=\"request\" type=\"tns:GetStopInfo_RequestRecord\"/></xs:sequence></xs:complexType><xs:complexType name=\"GetStopInfo_Response\"><xs:sequence><xs:element maxOccurs=\"unbounded\" minOccurs=\"0\" name=\"response\" type=\"tns:GetStopInfo_ResponseRecord\"/></xs:sequence></xs:complexType><xs:complexType name=\"GetStopInfo_RequestRecord\"><xs:sequence><xs:element minOccurs=\"0\" name=\"FUN_CODE\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"USER_ID\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"SIGN_TYPE\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"SIGN\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"REQ_ENCRYPTED\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"HOS_ID\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"DEPT_ID\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"DOCTOR_ID\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"BEGIN_DATE\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"END_DATE\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"PAGE_CURRENT\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"PAGE_SIZE\" type=\"xs:string\"/></xs:sequence></xs:complexType><xs:complexType name=\"GetStopInfo_ResponseRecord\"><xs:sequence><xs:element minOccurs=\"0\" name=\"RETURN_CODE\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"RETURN_MSG\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"SIGN_TYPE\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"SIGN\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"RES_ENCRYPTED\" type=\"xs:string\"/><xs:element minOccurs=\"0\" name=\"RES\" type=\"xs:string\"/></xs:sequence></xs:complexType></xs:schema></wsdl:types><wsdl:message name=\"GetStopInfo_Request\"><wsdl:part name=\"parameters\" element=\"tns:GetStopInfo_Request\"/></wsdl:message><wsdl:message name=\"GetStopInfo_Response\"><wsdl:part name=\"parameters\" element=\"tns:GetStopInfo_Response\"/></wsdl:message><wsdl:portType name=\"GetStopInfo\"><wsdl:operation name=\"GetStopInfo\"><wsdl:input name=\"GetStopInfo_Request\" message=\"tns:GetStopInfo_Request\"/><wsdl:output name=\"GetStopInfo_Response\" message=\"tns:GetStopInfo_Response\"/></wsdl:operation></wsdl:portType><wsdl:binding name=\"himapEntryServiceSoapBinding\" type=\"tns:GetStopInfo\"><soap:binding style=\"document\" transport=\"http://schemas.xmlsoap.org/soap/http\"/><wsdl:operation name=\"GetStopInfo\"><soap:operation soapAction=\"urn:GetStopInfo\" style=\"document\"/><wsdl:input name=\"GetStopInfo_Request\"><soap:body use=\"literal\"/></wsdl:input><wsdl:output name=\"GetStopInfo_Response\"><soap:body use=\"literal\"/></wsdl:output></wsdl:operation></wsdl:binding><wsdl:service name=\"himapEntryService\"><wsdl:port name=\"himapEntryPort\" binding=\"tns:himapEntryServiceSoapBinding\"><soap:address location=\"http://192.168.0.222:9222/himapws/webServices/himapEntryPort\"/></wsdl:port></wsdl:service></wsdl:definitions>";

    private String readFinal(String path) throws IOException {
        InputStream in = new FileInputStream(path);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while((len = in.read(buf)) != -1){
            out.write(buf,0,len);
        }
		return out.toString();
    }
    /**
     * @desc 拼接wsdl报文
     * @param wsdlList，每个服务的wsdlcontent
     * @param groupName，发布的组名
     * @return 一组服务发布的wsdl报文
     * @throws DocumentException
     */
    public static String jointWsdl(List<String> wsdlList,String groupName,String url) throws DocumentException {

        Document document = DocumentHelper.parseText(wsdlList.get(0));
        DefaultXPath schemaxpath = new DefaultXPath("wsdl:definitions/wsdl:types/xs:schema");
        DefaultXPath xpath = new DefaultXPath("wsdl:definitions/wsdl:types/xs:schema/*");
        DefaultXPath porttypexpath = new DefaultXPath("wsdl:definitions/wsdl:portType");
        DefaultXPath xpath2 = new DefaultXPath("wsdl:definitions/wsdl:portType/*");
        DefaultXPath bindingxpath = new DefaultXPath("wsdl:definitions/wsdl:binding");
        DefaultXPath xpath3 = new DefaultXPath("wsdl:definitions/wsdl:binding/wsdl:operation");
        DefaultXPath messagexpath = new DefaultXPath("wsdl:definitions");
        DefaultXPath xpath4 = new DefaultXPath("wsdl:definitions/wsdl:message");

        HashMap<String, String> map = new HashMap<>();
        map.put("wsdl","http://schemas.xmlsoap.org/wsdl/");
        map.put("xs","http://www.w3.org/2001/XMLSchema");

        schemaxpath.setNamespaceURIs(map);
        xpath.setNamespaceURIs(map);
        porttypexpath.setNamespaceURIs(map);
        xpath2.setNamespaceURIs(map);
        bindingxpath.setNamespaceURIs(map);
        xpath3.setNamespaceURIs(map);
        messagexpath.setNamespaceURIs(map);
        xpath4.setNamespaceURIs(map);

//        Element root = document.getRootElement();
//        Element address = (Element)root.selectSingleNode("wsdl:service/wsdl:port/*[@location]");
//        try {
//            address.addAttribute("location", url+"/webServices2?groupName=" + groupName);
////            address.addAttribute("location", getPro("config/misp-core.properties","msgComService.webServiceURL")
////                    +"/webServices?groupName=" + groupName);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        schemaxpath.setNamespaceURIs(map);
//        Element node = (Element)schemaxpath.selectSingleNode(document);
//        Namespace tns1 = node.getNamespaceForPrefix("tns");
//        node.remove(tns1);
//        node.addNamespace("tns", NAME_SPACE);
//        node.addAttribute("targetNamespace",NAME_SPACE);
//        root.addAttribute("targetNamespace",NAME_SPACE);
//        Namespace tns2 = root.getNamespaceForPrefix("tns");
//        root.remove(tns2);
//        root.addNamespace("tns",NAME_SPACE);
//
//
//        addSchemaHeader(schemaxpath,document);
//        addMessageHeader(messagexpath,document);
//        Element node1 = (Element)xpath3.selectSingleNode(document);
//        addBindingHeader(node1);

        for (int i = 1; i < wsdlList.size(); i++) {
            Document document2 = DocumentHelper.parseText(wsdlList.get(i));
            jointXML(document, document2, map, schemaxpath, xpath);
            jointXML(document, document2, map, porttypexpath, xpath2);
            jointXML(document, document2, map, bindingxpath, xpath3);
            jointXML(document, document2, map, messagexpath, xpath4);
        }

        return document.asXML();
    }

    public static void main(String[] args) throws DocumentException {
        List<String> wsdlList = new ArrayList<String>();
        wsdlList.add(xml1);
        wsdlList.add(xml2);
        Document document = DocumentHelper.parseText(modelXML);
        DefaultXPath schemaxpath = new DefaultXPath("wsdl:definitions/wsdl:types/xs:schema");
        DefaultXPath xpath = new DefaultXPath("wsdl:definitions/wsdl:types/xs:schema/*");
        DefaultXPath porttypexpath = new DefaultXPath("wsdl:definitions/wsdl:portType");
        DefaultXPath xpath2 = new DefaultXPath("wsdl:definitions/wsdl:portType/*");
        DefaultXPath bindingxpath = new DefaultXPath("wsdl:definitions/wsdl:binding");
        DefaultXPath xpath3 = new DefaultXPath("wsdl:definitions/wsdl:binding/wsdl:operation");
        DefaultXPath messagexpath = new DefaultXPath("wsdl:definitions");
        DefaultXPath xpath4 = new DefaultXPath("wsdl:definitions/wsdl:message");

        HashMap<String, String> map = new HashMap<>();
        map.put("wsdl","http://schemas.xmlsoap.org/wsdl/");
        map.put("xs","http://www.w3.org/2001/XMLSchema");

        schemaxpath.setNamespaceURIs(map);
        xpath.setNamespaceURIs(map);
        porttypexpath.setNamespaceURIs(map);
        xpath2.setNamespaceURIs(map);
        bindingxpath.setNamespaceURIs(map);
        xpath3.setNamespaceURIs(map);
        messagexpath.setNamespaceURIs(map);
        xpath4.setNamespaceURIs(map);

//        Element root = document.getRootElement();
//        Element address = (Element)root.selectSingleNode("wsdl:service/wsdl:port/*[@location]");
//        try {
//            address.addAttribute("location", "http://127.0.0.1:8076"+"/webServices2?groupName=" );
////            address.addAttribute("location", getPro("config/misp-core.properties","msgComService.webServiceURL")
////                    +"/webServices?groupName=" + groupName);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        packageParam("demo",document, map);

//        schemaxpath.setNamespaceURIs(map);
//        Element node = (Element)schemaxpath.selectSingleNode(document);
//        List schemaList = node.content().subList(0, 6);
//        Element schemaEle = (Element) schemaList.get(2);
//        schemaEle.addAttribute("name","demo");
//        Element complexEle1 = (Element) ((Element) ((Element) schemaList.get(4)).content().get(0)).content().get(0);
//        complexEle1.addAttribute("maxOccurs","1");
//        Element complexEle2 = (Element) ((Element) ((Element) schemaList.get(5)).content().get(0)).content().get(0);
//        complexEle2.addAttribute("maxOccurs","1");
//        node.setContent(schemaList);
//        Namespace tns1 = node.getNamespaceForPrefix("tns");
//        node.remove(tns1);
//        node.addNamespace("tns", NAME_SPACE);
//        node.addAttribute("targetNamespace",NAME_SPACE);
//        root.addAttribute("targetNamespace",NAME_SPACE);
//        Namespace tns2 = root.getNamespaceForPrefix("tns");
//        root.remove(tns2);
//        root.addNamespace("tns",NAME_SPACE);


//        addSchemaHeader(schemaxpath,document);
//        addMessageHeader(messagexpath,document);
//        Element node1 = (Element)xpath3.selectSingleNode(document);
//        addBindingHeader(node1);

        for (int i = 1; i < wsdlList.size(); i++) {
            Document document2 = DocumentHelper.parseText(wsdlList.get(i));
            jointXML(document, document2, map, schemaxpath, xpath);
            jointXML(document, document2, map, porttypexpath, xpath2);
            jointXML(document, document2, map, bindingxpath, xpath3);
            jointXML(document, document2, map, messagexpath, xpath4);
        }

        System.out.println(document.asXML());
    }

    private static void packageParam(String interfaceName,Document document, HashMap<String, String> map) {
        DefaultXPath reqXpath = new DefaultXPath
                ("wsdl:definitions/wsdl:types/xs:schema/xs:element[@name='"+interfaceName+"_Request']");
        reqXpath.setNamespaceURIs(map);
        DefaultXPath resXpath = new DefaultXPath
                ("wsdl:definitions/wsdl:types/xs:schema/xs:element[@name='"+interfaceName+"_Response']");
        resXpath.setNamespaceURIs(map);
        Element req = (Element)reqXpath.selectSingleNode(document);
        Element res = (Element)resXpath.selectSingleNode(document);
        Attribute reqName = req.attribute("name");
        Attribute reqType = req.attribute("type");
        reqName.setValue("xmlRequest");
        reqType.setValue("xs:string");
        Attribute resName = res.attribute("name");
        Attribute resType = res.attribute("type");
        resName.setValue("xmlResponse");
        resType.setValue("xs:string");
        Element schema = req.getParent();
        schema.clearContent();
        schema.add(req);
        schema.add(res);
    }

    public static String getPro(String file,String pro) throws IOException {
        InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(file);
        Properties properties = new Properties();
        properties.load(stream);
        return properties.getProperty(pro);
    }

    private static void addSchemaHeader(DefaultXPath schameXpath, Document document){
        Element parentElement = (Element)schameXpath.selectSingleNode(document);
        Element element = parentElement.addElement("xs:element");
        element.addAttribute("name","licenseInfo");
        element.addAttribute("type","tns:licenseInfo");
        Element complexType = parentElement.addElement("xs:complexType");
        complexType.addAttribute("name","licenseInfo");
        Element sequence = complexType.addElement("xs:sequence");
        Element complexElement1 = sequence.addElement("xs:element");
        complexElement1.addAttribute("name","username");
        complexElement1.addAttribute("type","xs:string");
        Element complexElement2 = sequence.addElement("xs:element");
        complexElement2.addAttribute("name","password");
        complexElement2.addAttribute("type","xs:string");
    }

    private static void addMessageHeader(DefaultXPath messageXpath, Document document){
        Element parentElement = (Element)messageXpath.selectSingleNode(document);
        Element element = parentElement.addElement("wsdl:message");
        element.addAttribute("name","licenseInfo");
        Element part = element.addElement("wsdl:part");
        part.addAttribute("name","licenseInfo");
        part.addAttribute("element","tns:licenseInfo");
    }


    private static void addBindingHeader(Element element){
        Element inputElement = element.element("input");
        Element soapHeader = inputElement.addElement("soap:header");
        soapHeader.addAttribute("message","tns:licenseInfo");
        soapHeader.addAttribute("part","licenseInfo");
        soapHeader.addAttribute("use","literal");
    }

    private static void jointXML(Document targetDocument, Document originDocument, HashMap<String, String> map,
                                 DefaultXPath
                                         parentXpath, DefaultXPath childXpath) {
        Element parentElement = (Element)parentXpath.selectSingleNode(targetDocument);
        List list = parentElement.content();
        List elements2 = childXpath.selectNodes(originDocument);
//        elements2 = packageSoap(parentElement, elements2);
        list.addAll(elements2);
        parentElement.setContent(list);
    }

    private static List packageSoap(Element parentElement, List elements2) {
        if (parentElement.getName().equals("binding")) {
//            parentElement.addAttribute("type","tns:service");
            Element element = (Element) elements2.get(0);
            element.addAttribute("name","demo2");
            addBindingHeader(element);
        }
        if (parentElement.getName().equals("portType")) {
//            parentElement.addAttribute("name","service");
            Element element = (Element) elements2.get(0);
            element.addAttribute("name","demo2");
            Element msgEle = (Element) element.content().get(0);
            msgEle.addAttribute("message","tns:demo2");
        }
        if (parentElement.getName().equals("definitions")) {
            Element element = (Element) elements2.get(0);
            element.addAttribute("name","demo2");
            Element msgEle = (Element) element.content().get(0);
            msgEle.addAttribute("element","tns:demo2");
        }
        if (parentElement.getName().equals("schema")) {
            List stringParam = ((Element)elements2.get(4)).content();

            elements2 = elements2.subList(0,4);
            Element reqEle = (Element) elements2.get(0);
            reqEle.addAttribute("name","demo2");
            Element resEle = (Element) elements2.get(1);
            resEle.addAttribute("type","tns:demo2Res");
//            Element complexEle1 = (Element) ((Element) ((Element) elements2.get(2)).content().get(0)).content().get(0);
//            complexEle1.addAttribute("maxOccurs","1");
//            complexEle1.addAttribute("name","xmlReq");
//            complexEle1.addAttribute("type","xs:string");
            Element complexEle1 = ((Element) elements2.get(2));
            complexEle1.clearContent();
            complexEle1.setContent(stringParam);


            Element complex = (Element) elements2.get(3);
            complex.addAttribute("name","demo2Res");
            Element complexEle2 = (Element) ((Element) ((Element) elements2.get(3)).content().get(0)).content().get(0);
            complexEle2.addAttribute("maxOccurs","1");
            complexEle2.addAttribute("name","xmlRes");
            complexEle2.addAttribute("type","xs:string");
        }
        return elements2;
    }

    @Test
    public void dealJson() throws IOException, DocumentException {
        String s = readFinal("C:\\Users\\Administrator\\Desktop\\20161025任务\\20161206\\出参.log");
        String s1 = s.substring(1,s.length()-3);
        System.out.println(s1);
        Document document = DocumentHelper.parseText(s1);
        Element root = document.getRootElement();
        String textTrim = root.getTextTrim();
        String s2 = textTrim.replace("\\n", "").replace("\\\"","\"");
        System.out.println(s2);

        JSONArray array = JSON.parseArray(s2);
    }

}
